import React from 'react';
import { Input, Tree, Empty } from 'antd';
import _ from 'lodash'

import './MeasurementTree.css';

import SparkChannel from '../ipc/sparkchannel'
import { TableType } from 'src/core/common';
import { buildStationNode, buildMeasurementNode, findNode, findAncestorNodes } from 'src/util/utils';

function fillPointDesc(treeData, pointNode) {
  const ancestors = findAncestorNodes(treeData, pointNode.key);
  const point = pointNode.data;
  point.station_desc = ancestors[0].data.station_desc;
  point.bay_desc = ancestors[1].data.bay_desc;
  point.device_desc = ancestors[2].data.device_desc;
  return point;
}

function searchTree(treeData, value) {
  const result = [];
  for (const node of treeData) {
    if (node.isLeaf) {
      const strTitle = node.title;
      const index = strTitle.indexOf(value);
      if (index > -1) {
        const beforeStr = strTitle.substring(0, index);
        const afterStr = strTitle.slice(index + value.length);
        const title =
          (
            <span>
              {beforeStr}
              <span className="site-tree-search-value">{value}</span>
              {afterStr}
            </span>
          );
        result.push({ ...node, title });
      }
    } else if (node.children) {
      const r = searchTree(node.children, value);
      for (const n of r) {
        result.push(n);
      }
    }
  }
  return result;
}

class MeasurementTree extends React.Component {
  constructor(props) {
    super(props);

    this.onLoadData = this.onLoadData.bind(this);
    this.onCheck = this.onCheck.bind(this);
    this.onLoad = this.onLoad.bind(this);
    this.onExpand = this.onExpand.bind(this);
    this.onSearch = _.debounce(this.onSearch.bind(this), 500);

    this.stationList = null;
    this.state = {
      treeData: [],
      loadedKeys: [],
      expandedKeys: [],
      checkedPoints: this.props.value || [],

      searchValue: '',
      searchList: [],
    };
  }

  async getStationData() {
    if (this.props.curveApi) {
      const channel = await SparkChannel();
      let resp = await channel.request_get_model_node_list();
      // console.log('get terminal result', resp);
      return resp.data.model_node_list;
    } else {
      const channel = await SparkChannel();
      let resp = await channel.request_get_model_node_list();
      // console.log('get terminal result', resp);
      return resp.data.model_node_list;
    }
  }

  async getPointList(node) {
    const tableType = this.props.tableType;
    const table_type = TableType.getTableTypeId(tableType);
    const device = node.data;
    const device_id = device.device_id;

    if (this.props.curveApi) {
      const channel = await SparkChannel();
      let resp = await channel.request_get_point_list({ device_id, data_type: table_type });
      return resp.data.point_list;
    } else {

      const channel = await SparkChannel();
      let resp = await channel.request_get_point_list({ device_id, data_type: table_type });
      return resp.data.point_list;
    }
  }

  async componentDidMount() {
    try {
      this.stationList = await this.getStationData();
      const treeData = this.stationList.map(s => buildStationNode(s));
      this.setState({ treeData });
    } catch (err) {
      console.log('get sites fail', err)
    }
  }

  componentDidUpdate(prevProps) {
    if (prevProps.tableType !== this.props.tableType && this.stationList) {
      // 清理points数据
      const treeData = this.stationList.map(s => buildStationNode(s));
      this.setState({
        treeData,
        loadedKeys: [],
        expandedKeys: [],
        checkedPoints: [],
        searchValue: '',
        searchList: [],
      });

      if (!_.isEmpty(this.props.value)) {
        this.props.onChange && this.props.onChange([]);
      }
    }
  }

  async onLoadData(node) {
    const { key, children } = node;
    console.log('onLoadData', node)

    if (!_.startsWith(key, "TERMINAL") && !_.startsWith(key, "DEVICE")) {
      return;
    }
    if (children) {
      return;
    }

    // 拷贝一份tree，修改node
    const treeData = [...this.state.treeData];
    let targetNode = findNode(treeData, key);
    let points = await this.getPointList(node);
    // console.log('get measurements result', points);
    targetNode.children = points.map(s => buildMeasurementNode(s));
    this.setState({ treeData: treeData });
  }

  onCheck(checkedKeysValue, event) {
    console.log('onCheck', checkedKeysValue, event);
    // this.setState({ checkedKeys: checkedKeysValue });
    // const points = event.checkedNodes.map(n => n.data);
    const points = this.state.checkedPoints || [];
    const pt = event.node.data;
    if (event.checked) {
      const pt2 = fillPointDesc(this.state.treeData, event.node);
      points.push(pt2);
    } else {
      const index = points.findIndex(p => p.point_id === pt.point_id);
      points.splice(index, 1);
    }

    this.setState({ checkedPoints: points });
    this.props.onChange && this.props.onChange(points);
  }

  onLoad(loadedKeys) {
    this.setState({ loadedKeys });
  }

  onExpand(expandedKeys) {
    this.setState({ expandedKeys });
  }

  onSearch(e) {
    const searchValue = e.target.value;
    const searchList = searchTree(this.state.treeData, searchValue);
    this.setState({ searchValue, searchList });
  }

  render() {
    let checkedKeys = this.state.checkedPoints.map(point => `POINT-${point.point_id}`);
    let tree = this.state.treeData;
    if (this.state.searchValue) {
      tree = this.state.searchList;
      checkedKeys = tree.map(n => n.key).filter(key => checkedKeys.includes(key));
    }

    return (
      <div className='measurement-tree'>
        <Input.Search
          style={{
            marginBottom: 8,
          }}
          placeholder="搜索"
          onChange={this.onSearch}
        />
        <Tree showIcon checkable
          treeData={tree}
          checkedKeys={checkedKeys}
          expandedKeys={this.state.expandedKeys}
          loadedKeys={this.state.loadedKeys}
          onCheck={this.onCheck}
          loadData={this.onLoadData}
          onLoad={this.onLoad}
          onExpand={this.onExpand} />
        {this.state.searchValue && _.isEmpty(tree) && <Empty />}
      </div>);
  }
}

export default MeasurementTree